package toy.keli.picmap.model;

import android.graphics.Point;
import android.graphics.PointF;
import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.constraintlayout.widget.ConstraintLayout;

import toy.keli.picmap.util.utilCallback;

/**
 * 常用事件汇总
 */
public class event0 {
    //可拖拽
    public static void canDrag(View view){
        Point p = system.getScreenSize(view.getContext());
        canDrag(view, p.x, p.y, (v) -> {});
    }
    public static void canDrag(View view, int x, int y){canDrag(view, x, y, (v) -> {});    }
    public static void canDrag(View view, int x, int y, utilCallback.view endDo) {

        view.setOnTouchListener(new View.OnTouchListener() {
                private int width=0; //  测量宽度 FreeView的宽度
                private int height; // 测量高度 FreeView的高度
                private int maxWidth; // 最大宽度 window 的宽度
                private int maxHeight; // 最大高度 window 的高度
                private float downX; //点击时的x坐标
                private float downY;  // 点击时的y坐标
                //是否拖动标识
                private boolean isDrag=false;
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    //v.getParent().requestDisallowInterceptTouchEvent(true);
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_DOWN: // 点击动作处理 每次点击时将拖动状态改为 false 并且记录下点击时的坐标 downX downY
                            isDrag=false;
                            downX = event.getX(); // 点击触屏时的x坐标 用于离开屏幕时的x坐标作计算
                            downY = event.getY(); // 点击触屏时的y坐标 用于离开屏幕时的y坐标作计算
                            if(width==0){
                                width=view.getWidth();
                                height=view.getHeight();
                                maxWidth=x;
                                maxHeight=y;
                            }
                            return true;
                           // break;
                        case MotionEvent.ACTION_MOVE: // 滑动动作处理 记录离开屏幕时的 moveX  moveY 用于计算距离 和 判断滑动事件和点击事件 并作出响应
                            final float moveX = event.getX() - downX;
                            final float moveY = event.getY() - downY;
                            int l,r,t,b; // 上下左右四点移动后的偏移量
                            //计算偏移量 设置偏移量 = 3 时 为判断点击事件和滑动事件的峰值
                            if (Math.abs(moveX) > 3 ||Math.abs(moveY) > 3) { // 偏移量的绝对值大于 3 为 滑动时间 并根据偏移量计算四点移动后的位置
                                l = (int) (view.getLeft() + moveX);
                                r = l+width;
                                t = (int) (view.getTop() + moveY);
                                b = t+height;
                                //不划出边界判断,最大值为边界值
                                // 如果你的需求是可以划出边界 此时你要计算可以划出边界的偏移量 最大不能超过自身宽度或者是高度  如果超过自身的宽度和高度 view 划出边界后 就无法再拖动到界面内了 注意
                                if(l<0){ // left 小于 0 就是滑出边界 赋值为 0 ; right 右边的坐标就是自身宽度 如果可以划出边界 left right top bottom 最小值的绝对值 不能大于自身的宽高
                                    l=0;
                                    r=l+width;
                                }else if(r> maxWidth){ // 判断 right 并赋值
                                    r= maxWidth;
                                    l=r-width;
                                }
                                if(t<0){ // top
                                    t=0;
                                    b=t+height;
                                }else if(b> maxHeight){ // bottom
                                    b= maxHeight;
                                    t=b-height;
                                }
                                view.layout(l, t, r, b); // 重置view在layout 中位置
                                isDrag=true;  // 重置 拖动为 true
                                view.setPressed(false);
                            }
                            break;
                        case MotionEvent.ACTION_UP: // 松开
                            if(isDrag){
                                log.debug("up save poiston");
                                //保存元素参数  防止重新绘制被还原  https://blog.csdn.net/qq1104261989/article/details/74930445
                                ConstraintLayout.LayoutParams lpFeedback = (ConstraintLayout.LayoutParams)v.getLayoutParams();
                                lpFeedback.setMargins(v.getLeft(), v.getTop(),0,maxHeight-v.getBottom());
                                v.setLayoutParams(lpFeedback);
                                isDrag=false;
                                endDo.call(v);

                            }
                            break;
                        case MotionEvent.ACTION_CANCEL: // 不处理
                            //view.setPressed(false);
                            break;
                    }
                    return false;
                }
            });
    }

    public enum type{
        LEFT,RIGHT,UP,DOWN,CLICK,LONGCLICK,DCLICK,       //向左，向右，向上 ，向下，长按,双击
        DRAG,ZOOM                           //两指拖动，缩放，
        ,ZOOM_OVER
    }
    public static PointF begin=new PointF(0,0);         //拖拽的起始位置
    public static PointF end=new PointF(0,0);
    public static float zoomScale=1;      //缩放的长度
    public static long slideTime=0;
    public static  void bind(View view,callback func){
        bindClick(view,func);
        bindTouch(view,func);
    }
    public static  void bindClick(View view,callback func){
        view.setOnClickListener(new View.OnClickListener() {
            //            private static final long DOUBLE_TIME = 300;
//            private long lastClickTime = 0;
            private boolean timerClick = false;
            private int clickNum = 0;
            @Override
            public void onClick(View v) {
                clickNum++;
                if (!timerClick)
                    timerClick = new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            if (clickNum == 1) {
                                long currentTimeMillis = System.currentTimeMillis();
                                if(currentTimeMillis-slideTime>800)
                                    func.call(type.CLICK);
                            } else
                                func.call(type.DCLICK);
                            timerClick = false;
                            clickNum = 0;
                        }
                    }, 300);    //延时300执行
            }
        });
        //Android Button四种点击事件和长按事件 https://blog.csdn.net/weixin_30819085/article/details/98852484
        view.setOnLongClickListener(new View.OnLongClickListener(){
            @Override
            public boolean onLongClick(View v) {
                if(zoomScale==1) func.call(type.LONGCLICK);
                return true;
            }
        });
    }
    public static  void bindTouch(View view, callback func){
        //Muilti-touch 双指缩放的实现探索： https://www.cnblogs.com/akira90/archive/2013/03/10/2952886.html
        view.setOnTouchListener(new View.OnTouchListener() {
            private float moveX;
            private float moveY;
            private float pressX;
            private float pressY;
            private type mode;  //用于标记模式
            private PointF mPoint;//中心点
            private float length;//两点之间的距离
            private float _zoomScale=1;//两点之间的距离
            //滑动调用
            void slideCall(type t){
                slideTime= system.time();
                func.call(t);
            }
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    //按下
                    case MotionEvent.ACTION_DOWN:
                        pressX = event.getX();
                        pressY = event.getY();
                        begin.x=pressX;   begin.y=pressY;
                        mode= type.DRAG;
                        //return true;
                        //break;
                    //移动
                    case MotionEvent.ACTION_MOVE:
//                        if(mode!=null){
//                            float dx = event.getX() - moveX;//x轴移动距离
//                            float dy = event.getY() - moveY;
//                            if(dx<10f && dy<10f)
//                                return true;
//                        }
                        //android图片缩放、放大demo - Android实例教程  https://www.cnblogs.com/ywq-come/p/5926655.html
                        if (mode == type.DRAG) {//图片拖动事件
                            begin.x=moveX;
                            begin.y=moveY;
                            end.x=event.getX();
                            end.y=event.getY();
                            if(moveX*moveY==0){
                                begin.x=end.x;
                                begin.y=end.y;
                            }
                            func.call(type.DRAG);
                        } else if(mode == type.ZOOM && event.getPointerCount()>1) {//图片缩放事件
                            float dx = event.getX(1) - event.getX(0);
                            float dy = event.getY(1) - event.getY(0);
                            begin=mPoint;
                            zoomScale= (float)Math.sqrt(dx*dx + dy*dy)/length *_zoomScale;
                            func.call(type.ZOOM);
                        }
                        moveX = event.getX();
                        moveY = event.getY();
                        break;
                    //松开
                    case MotionEvent.ACTION_UP:
                        moveX = event.getX();
                        moveY = event.getY();
                        float dy = Math.abs(moveY - pressY);
                        float dx = Math.abs(moveX - pressX);
                        if(dx+dy<20) {
                            v.performClick();
                            break;
                        }
                        if(dx>dy) {
                            if (moveX - pressX > 0) {
                                slideCall(type.RIGHT);
                                Log.i("message", "向右");
                            } else if (moveX - pressX < 0) {
                                slideCall(type.LEFT);
                                Log.i("message", "向左");
                            }
                        }else {
                            if (moveY - pressY > 0) {
                                Log.i("message", "向下");
                                slideCall(type.DOWN);
                            } else{
                                Log.i("message", "向上");
                                slideCall(type.UP);
                            }
                        }

                        func.call(type.ZOOM_OVER);
                        moveX = moveY = 0;
                        mode=null;
                        //MotionEvent.st
                        break;
                    //当屏幕上已经有一个点被按住，此时再按下其他点时触发。
                    case MotionEvent.ACTION_POINTER_DOWN:
                        float dx2 = event.getX(1) - event.getX(0);
                        float dy2 = event.getY(1) - event.getY(0);
                        length= (float)Math.sqrt(dx2*dx2 + dy2*dy2);
                        if(length > 10f){//两点之间的距离足够长 避免手指上有两个茧
                            float midx = event.getX(1) + event.getX(0);
                            float midy = event.getY(1) + event.getY(0);

                            mPoint=new PointF(midx/2, midy/2);
                            _zoomScale=zoomScale;
                            mode= type.ZOOM;
                            //func.call(type.ZOOM);
                        }

                    default:
                        break;
                }
                return false;
            }
        });
    }


    public interface callback{
        void call(event0.type t);
    }
}
